package org.fujay.langchain4jserver.infrastructure.persistence.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.fujay.langchain4jserver.domain.application.entity.AppConfigHistory;
import org.fujay.langchain4jserver.domain.application.repository.AppConfigHistoryRepository;
import org.fujay.langchain4jserver.domain.application.vo.AppConfigSnapshot;
import org.fujay.langchain4jserver.domain.application.vo.AppId;
import org.fujay.langchain4jserver.domain.application.vo.Version;
import org.fujay.langchain4jserver.infrastructure.persistence.mybatis.entity.AppConfigHistoryPo;
import org.fujay.langchain4jserver.infrastructure.persistence.mybatis.mapper.AppConfigHistoryMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 应用配置历史仓储实现
 */
@Slf4j
@Repository
@RequiredArgsConstructor
public class AppConfigHistoryRepositoryImpl implements AppConfigHistoryRepository {

    private final AppConfigHistoryMapper historyMapper;
    private final ObjectMapper objectMapper; // 用于 JSON 序列化/反序列化

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(AppConfigHistory history) {
        AppConfigHistoryPo po = convertToPO(history);
        // 假设历史记录总是插入新的
        historyMapper.insert(po);
    }

    @Override
    public List<AppConfigHistory> findByAppId(AppId appId) {
        LambdaQueryWrapper<AppConfigHistoryPo> queryWrapper =
                Wrappers.<AppConfigHistoryPo>lambdaQuery()
                        .eq(AppConfigHistoryPo::getAppId, appId.value())
                        .orderByDesc(AppConfigHistoryPo::getVersion); // 按版本降序
        List<AppConfigHistoryPo> pos = historyMapper.selectList(queryWrapper);
        return pos.stream().map(this::convertToDomain).collect(Collectors.toList());
    }

    @Override
    public Optional<AppConfigHistory> findByAppIdAndVersion(AppId appId, Version version) {
        LambdaQueryWrapper<AppConfigHistoryPo> queryWrapper =
                Wrappers.<AppConfigHistoryPo>lambdaQuery()
                        .eq(AppConfigHistoryPo::getAppId, appId.value())
                        .eq(AppConfigHistoryPo::getVersion, version.value());
        AppConfigHistoryPo po = historyMapper.selectOne(queryWrapper);
        return Optional.ofNullable(po).map(this::convertToDomain);
    }

    @Override
    public Optional<Version> findMaxVersionByAppId(AppId appId) {
        Integer maxVersionInt = historyMapper.selectMaxVersionByAppId(appId.value());
        return Optional.ofNullable(maxVersionInt).map(Version::new);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByAppId(AppId appId) {
        LambdaQueryWrapper<AppConfigHistoryPo> deleteWrapper =
                Wrappers.<AppConfigHistoryPo>lambdaQuery().eq(AppConfigHistoryPo::getAppId, appId.value());
        historyMapper.delete(deleteWrapper);
    }

    // --- Conversion Methods --- (可移至 Assembler)

    private AppConfigHistory convertToDomain(AppConfigHistoryPo po) {
        if (po == null) return null;

        AppId appId = new AppId(po.getAppId());
        Version version = new Version(po.getVersion());
        AppConfigSnapshot snapshot;
        try {
            snapshot = objectMapper.readValue(po.getConfigSnapshotJson(), AppConfigSnapshot.class);
        } catch (JsonProcessingException e) {
            log.error(
                    "Failed to deserialize AppConfigSnapshot for history appId: {}, version: {}. Error: {}",
                    appId.value(),
                    version.value(),
                    e.getMessage());
            snapshot = AppConfigSnapshot.builder().build();
        }

        // 使用 AppConfigHistory.load 静态方法加载
        return AppConfigHistory.load(
                po.getId(),
                appId,
                version,
                snapshot,
                po.getChangeDescription(),
                po.getCreateBy(),
                po.getCreateTime());
    }

    private AppConfigHistoryPo convertToPO(AppConfigHistory history) {
        if (history == null) return null;

        AppConfigHistoryPo po = new AppConfigHistoryPo();
        po.setAppId(history.getAppId().value());
        po.setVersion(history.getVersion().value());
        po.setChangeDescription(history.getChangeDescription());
        po.setCreateTime(history.getChangeTime());
        po.setCreateBy(history.getChangedBy());
        try {
            po.setConfigSnapshotJson(objectMapper.writeValueAsString(history.getConfigSnapshot()));
        } catch (JsonProcessingException e) {
            log.error(
                    "Failed to serialize AppConfigSnapshot for history appId: {}, version: {}. Error: {}",
                    history.getAppId().value(),
                    history.getVersion().value(),
                    e.getMessage());
            po.setConfigSnapshotJson("{ \"error\": \"Serialization failed\" }"); // 记录错误信息
        }
        return po;
    }
}
